package com.glink.manage.service.Impl;


import com.alibaba.nacos.common.utils.CollectionUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.glink.common.contants.BaseCodeConstants;
import com.glink.common.exception.GeneralSimpleException;
import com.glink.common.util.BaseCommonUtils;
import com.glink.manage.common.Constants;
import com.glink.manage.domain.BarriersBean;
import com.glink.manage.domain.ConstructionWorkBean;
import com.glink.manage.domain.ConstructionWorkSiteBean;
import com.glink.manage.domain.OrgBean;
import com.glink.manage.dto.barriers.*;
import com.glink.manage.mapper.BarriersMapper;
import com.glink.manage.service.BarriersService;
import com.glink.manage.service.CodeService;
import com.glink.manage.service.OrgService;
import com.glink.manage.service.UserService;
import com.glink.manage.vo.barriers.BarriersBaseVO;
import com.glink.manage.vo.barriers.BarriersFindVO;
import com.glink.manage.vo.barriers.BarriersTreeVO;
import com.glink.manage.vo.barriers.BarriersVO;
import com.glink.manage.vo.code.CodeVO;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;


@Service
public class BarriersServiceImpl extends ServiceImpl<BarriersMapper, BarriersBean> implements BarriersService {

    @Autowired
    private BarriersMapper barriersMapper;
    
    @Autowired
    private ConstructionWorkServiceImpl constructionWorkService;

    @Autowired
    private ConstructionWorkSiteServiceImpl constructionWorkSiteService;

    @Autowired
    private OrgService orgService;

    @Autowired
    private CodeService codeService;

    @Autowired
    private UserService userService;


    /**
     * 分页查询行人设备
     * @param barriersPageDTO 查询信息
     * @return 行人设备信息
     */
    @Override
    public IPage<BarriersVO> findBarriersPagePeople(BarriersPageDTO barriersPageDTO) throws GeneralSimpleException {
        return findBarriersPage(barriersPageDTO, BaseCodeConstants.CodeType_BarrierGateType.KEY_BarrierGateType02);
    }

    /**
     * 分页查询车辆设备
     * @param barriersPageDTO 查询信息
     * @return 车辆设备信息
     */
    @Override
    public IPage<BarriersVO> findBarriersPageCar(BarriersPageDTO barriersPageDTO) throws GeneralSimpleException {
        return findBarriersPage(barriersPageDTO, BaseCodeConstants.CodeType_BarrierGateType.KEY_BarrierGateType01);
    }

    public IPage<BarriersVO> findBarriersPage(BarriersPageDTO barriersPageDTO, String distinguish) throws GeneralSimpleException {
        boolean headOffice = userService.checkHeadOffice();
        List<String> workIdList = null;
        if (!headOffice) {
            List<String> orgIdList = orgService.getDataPermissionOrgId();
            if(CollectionUtils.isNotEmpty(orgIdList)){
                // 1. 通过权限筛选出对应的工程列表
                workIdList = this.constructionWorkService.findIdByProjectDepartmentObjIdIn(orgIdList);
            }
            if(CollectionUtils.isEmpty(workIdList)){
                return new Page<>(barriersPageDTO.getPage(), barriersPageDTO.getSize());
            }
        }
        
        //1.创建分页对象,以BarriersBean 为蓝本，
        Page<BarriersBean> page = new Page<>(barriersPageDTO.getPage(), barriersPageDTO.getSize());

        //2.构建查询条件 LambdaQueryWrapper
        LambdaQueryWrapper<BarriersBean> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BarriersBean::getDistinguish, distinguish);
        queryWrapper.eq(BarriersBean::getIfDelete, BaseCodeConstants.CodeType_WhetherCode.KEY_WhetherCode02);
        
        queryWrapper.in(!headOffice, BarriersBean::getConstructionWorkObjId, workIdList);

        //3.判断dto的三个字段进入分支
        if (StringUtils.isNotEmpty(barriersPageDTO.getConstructionWorkObjId())) {
            // 如果传入了工程ID，则进行工程ID查询
            queryWrapper.eq(BarriersBean::getConstructionWorkObjId, barriersPageDTO.getConstructionWorkObjId());
        }
        if (StringUtils.isNotEmpty(barriersPageDTO.getConstructionWorkSiteObjId())) {
            // 如果传入了施工现场名称，则进行施工现场名称查询
            queryWrapper.eq(BarriersBean::getConstructionWorkSiteObjId, barriersPageDTO.getConstructionWorkSiteObjId());
        }
        if (StringUtils.isNotEmpty(barriersPageDTO.getObjId())) {
            // 如果传入了设备ID，则进行设备ID查询
            queryWrapper.eq(BarriersBean::getObjId, barriersPageDTO.getObjId());
        }

        // 4. 调用 Mapper 层的分页查询方法
        IPage<BarriersBean> resultPage = barriersMapper.selectPage(page, queryWrapper);

        // 5. 将查询结果转换为 VO 对象
        IPage<BarriersVO> barriersVOPage = resultPage.convert(barriersBean -> {
            BarriersVO barriersVO = new BarriersVO();
            BeanUtils.copyProperties(barriersBean, barriersVO); // 将 BarriersBean 属性复制到 BarriersVO

            //获取工程名
            String name = constructionWorkService.findNameByObjId(barriersBean.getConstructionWorkObjId());
            // 获取施工现场名称
            String siteName = constructionWorkSiteService.findNameByObjId(barriersBean.getConstructionWorkSiteObjId());  // 获取施工现场名称
            
            //在set回barriersVO
            barriersVO.setConstructionWorkName(name);
            barriersVO.setConstructionWorkSiteName(siteName);  // 设置施工现场名称
            return barriersVO;
        });

        // 6. 返回分页结果
        return barriersVOPage;
    }


    /**
     * 保存行人设备
     * @param barriersDTO 保存行人设备信息
     * @return 保存行人设备状态
     */
    @Override
    @Transactional(value = "transactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public boolean saveBarriersPeople(BarriersDTO barriersDTO) throws GeneralSimpleException {
        return saveBarriers(barriersDTO, BaseCodeConstants.CodeType_BarrierGateType.KEY_BarrierGateType02);
    }

    /**
     * 保存车辆设备
     * @param barriersDTO 保存车辆设备信息
     * @return 保存车辆设备状态
     */
    @Override
    @Transactional(value = "transactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public boolean saveBarriersCar(BarriersDTO barriersDTO) throws GeneralSimpleException {
        return saveBarriers(barriersDTO, BaseCodeConstants.CodeType_BarrierGateType.KEY_BarrierGateType01);
    }

    @Transactional(value = "transactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public boolean saveBarriers(BarriersDTO barriersDTO, String distinguish) throws GeneralSimpleException {

        if(StringUtils.isNotBlank(barriersDTO.getConstructionWorkSiteObjId())){
            // 校验场站授权
            constructionWorkSiteService.checkGrantByObjId(barriersDTO.getConstructionWorkSiteObjId());
        }
        
        // 校验设备序列号是否使用过
        checkFactorySerialNumber(barriersDTO.getFactorySerialNumber(), null);
        
        // 生成一个新的设备ID(uuid)
        String deviceId= BaseCommonUtils.generateUUID();  // 调用生成的UUID的方法

        // 新增(保存)设备数据
        BarriersBean barriers = new BarriersBean();
        barriers.setObjId(deviceId);

        barriers.setDistinguish(distinguish);

        barriers.setConstructionWorkObjId(barriersDTO.getConstructionWorkObjId());
        barriers.setConstructionWorkSiteObjId(barriersDTO.getConstructionWorkSiteObjId());
        barriers.setBrand(barriersDTO.getBrand());
        barriers.setModel(barriersDTO.getModel());
        barriers.setFactorySerialNumber(barriersDTO.getFactorySerialNumber());
        barriers.setIp(barriersDTO.getIp());
        barriers.setPort(barriersDTO.getPort());
        barriers.setOnlineStatus(BaseCodeConstants.CodeType_WhetherCode.KEY_WhetherCode02);
        barriers.setIfDelete(BaseCodeConstants.CodeType_WhetherCode.KEY_WhetherCode02);
        return this.save(barriers);
    }

    /**
     * 校验设备号
     * @param factorySerialNumber 设备号
     */
    private void checkFactorySerialNumber(String factorySerialNumber, String objId) throws GeneralSimpleException {
        if(StringUtils.isNotBlank(factorySerialNumber)){
            Integer count = this.lambdaQuery()
                    .eq(BarriersBean::getFactorySerialNumber, factorySerialNumber)
                    .eq(BarriersBean::getIfDelete, BaseCodeConstants.CodeType_WhetherCode.KEY_WhetherCode02)
                    .ne(StringUtils.isNotEmpty(objId), BarriersBean::getObjId, objId)
                    .count();
            if(Objects.nonNull(count) && count > 0){
                throw new GeneralSimpleException("403003", factorySerialNumber);
            }
        }
    }

    /**
     * 更新设备信息
     * @param barriersUpdateDTO 更新设备信息
     * @return 更新设备信息状态
     */
    @Override
    @Transactional(value = "transactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public boolean updateBarriers(BarriersUpdateDTO barriersUpdateDTO) throws GeneralSimpleException {
        // 更新设备数据
        BarriersBean barriers = this.getById(barriersUpdateDTO.getObjId());
        if (barriers != null) {

            checkFactorySerialNumber(barriersUpdateDTO.getFactorySerialNumber(), barriersUpdateDTO.getObjId());

            barriers.setConstructionWorkObjId(barriersUpdateDTO.getConstructionWorkObjId());
            barriers.setConstructionWorkSiteObjId(barriersUpdateDTO.getConstructionWorkSiteObjId());
            barriers.setBrand(barriersUpdateDTO.getBrand());
            barriers.setModel(barriersUpdateDTO.getModel());
            barriers.setFactorySerialNumber(barriersUpdateDTO.getFactorySerialNumber());
            barriers.setIp(barriersUpdateDTO.getIp());
            barriers.setPort(barriersUpdateDTO.getPort());

            return this.updateById(barriers);
        }
        return false;
    }

    /**
     * 删除设备
     * @param objIdList 删除设备信息
     * @return 删除设备状态
     */
    @Override
    @Transactional(value = "transactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public boolean deleteBarriers(List<String> objIdList) {
        // 批量删除设备
        //  "[1, 2, 3, 4]
        //id 列表
        List<BarriersBean> barriersBeanList = this.lambdaQuery().in(BarriersBean::getObjId, objIdList).list();
        if(CollectionUtils.isNotEmpty(barriersBeanList)){
            barriersBeanList.forEach(barriersBean -> barriersBean.setIfDelete(BaseCodeConstants.CodeType_WhetherCode.KEY_WhetherCode01));
            return updateBatchById(barriersBeanList);
        }
        return false;
    }

    /**
     * 导出 设备 信息
     * @param barriersPageDTO 导出设备信息
     * @param distinguish 行人/车辆
     * @return 设备信息
     * @throws IOException 输出
     */
    @Override
    public ByteArrayOutputStream exportBarriersData(BarriersPageDTO barriersPageDTO, String distinguish) throws IOException {
        // 1. 创建查询条件 LambdaQueryWrapper
        LambdaQueryWrapper<BarriersBean> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BarriersBean::getDistinguish, distinguish);
        queryWrapper.eq(BarriersBean::getIfDelete, BaseCodeConstants.CodeType_WhetherCode.KEY_WhetherCode02);

        // 根据 DTO 的字段构造筛选条件
        if (StringUtils.isNotEmpty(barriersPageDTO.getConstructionWorkObjId())) {
            queryWrapper.eq(BarriersBean::getConstructionWorkObjId, barriersPageDTO.getConstructionWorkObjId());
        }
        if (StringUtils.isNotEmpty(barriersPageDTO.getConstructionWorkSiteObjId())) {
            queryWrapper.eq(BarriersBean::getConstructionWorkSiteObjId, barriersPageDTO.getConstructionWorkSiteObjId());
        }
        if (StringUtils.isNotEmpty(barriersPageDTO.getObjId())) {
            queryWrapper.eq(BarriersBean::getObjId, barriersPageDTO.getObjId());
        }

        // 2. 根据查询条件获取筛选后的数据
        List<BarriersBean> barriersBeanList = barriersMapper.selectList(queryWrapper);

        // 3. 创建 Excel 工作簿
        Workbook workbook = new XSSFWorkbook();
        Sheet sheet = workbook.createSheet("设备信息");

        // 4. 创建表头
        Row headerRow = sheet.createRow(0);
        String[] headers = {"所属工程", "所属施工现场", "品牌", "型号", "在线状态(0离线/1在线)", "创建时间"};
        for (int i = 0; i < headers.length; i++) {
            Cell cell = headerRow.createCell(i);
            cell.setCellValue(headers[i]);
        }

        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        // 5. 填充数据
        int rowIndex = 1;
        for (BarriersBean barriersBean : barriersBeanList) {
            Row row = sheet.createRow(rowIndex++);

            //获取工程名
            String name = constructionWorkService.findNameByObjId(barriersBean.getConstructionWorkObjId());
            // 获取施工现场名称
            String siteName = constructionWorkSiteService.findNameByObjId(barriersBean.getConstructionWorkSiteObjId());
 
            // 要回显
            row.createCell(0).setCellValue(name);
            row.createCell(1).setCellValue(siteName);


            //码值替换
            List<CodeVO> Band = codeService.findByTypeList(Collections.singletonList(BaseCodeConstants.CodeType_02.KEY_BrandType));
            Map<String, String> carTypeMap = Maps.newHashMap();
            if (CollectionUtils.isNotEmpty(Band)) {
                carTypeMap = Band.stream().collect(Collectors.toMap(CodeVO::getKey, CodeVO::getName));
            }

            // 获取 barriersBean.getBrand() 的值，并查找对应的 name
            String brandKey = barriersBean.getBrand(); // 假设 getBrand 返回的是键
//            if (carTypeMap.containsKey(brandKey)) {
//                String nameValue = carTypeMap.get(brandKey);
//                System.out.println("找到键 " + brandKey + " 对应的 name: " + nameValue);
//            } else {
//                System.out.println("未找到键 " + brandKey);
//            }


            row.createCell(2).setCellValue(carTypeMap.get(brandKey));
            row.createCell(3).setCellValue(barriersBean.getModel());
            // row.createCell(6).setCellValue(barriersBean.getFactorySerialNumber());
            // row.createCell(7).setCellValue(barriersBean.getIp());
            // row.createCell(8).setCellValue(barriersBean.getPort());
            row.createCell(4).setCellValue(barriersBean.getOnlineStatus());


            String formattedDate = dateFormat.format(barriersBean.getCreateTime());


            row.createCell(5).setCellValue(formattedDate);
        }

        // 6. 将工作簿内容写入字节流
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        workbook.write(outputStream);
        workbook.close();

        // 7. 返回字节流
        return outputStream;
    }


    /**
     * 根据id找设备信息
     * @param barriersFindDTO 主键ID
     * @param distinguish 行人/车辆
     * @return 行人/车辆设备信息
     */
    @Override
    public BarriersFindVO findBarriers(BarriersFindDTO barriersFindDTO, String distinguish) {
        BarriersBean barriersBean = this.getById(barriersFindDTO.getObjId());

        BarriersFindVO barriersFindVO = new BarriersFindVO();

        BeanUtils.copyProperties(barriersBean, barriersFindVO);

        //获取工程名
        String name = constructionWorkService.findNameByObjId(barriersBean.getConstructionWorkObjId());
        // 获取施工现场名称
        String siteName = constructionWorkSiteService.findNameByObjId(barriersBean.getConstructionWorkSiteObjId());


        barriersFindVO.setConstructionWorkName(name);
        barriersFindVO.setConstructionWorkSiteName(siteName);

        return barriersFindVO;
    }


    /**
     * 树结构
     * @param barriersTreeDTO 树结构信息
     * @return 树结构信息
     * @throws GeneralSimpleException 输出
     */
    @Override
    public List<BarriersTreeVO> findTree(BarriersTreeDTO barriersTreeDTO) throws GeneralSimpleException {

        // 获取设备类型筛选条件
        String distinguish = barriersTreeDTO.getDistinguish();
        if (StringUtils.isBlank(distinguish)) {
            throw new GeneralSimpleException("400053");
        }

        boolean headOffice = userService.checkHeadOffice();
        List<String> orgIdList = null;
        if (!headOffice) {
            orgIdList = orgService.getDataPermissionOrgId();
            if(CollectionUtils.isEmpty(orgIdList)){
                return Lists.newArrayList();
            }
        }

        // 1. 通过权限筛选出对应的工程列表
        List<ConstructionWorkBean> constructionWorkBeanList = this.constructionWorkService.findByIsHeadOfficeAndProjectDepartmentObjIdInOrderByProjectDepartmentOrgOrderAsc(headOffice, orgIdList);

        List<BarriersTreeVO> treeList = Lists.newArrayList();
        if (CollectionUtils.isNotEmpty(constructionWorkBeanList)) {
            // 获取所有工程的 ID
            List<String> workIds = constructionWorkBeanList.stream()
                    .map(ConstructionWorkBean::getObjId)
                    .collect(Collectors.toList());

            // 工程现场
            
            List<ConstructionWorkSiteBean> workSiteBeanList = constructionWorkSiteService.findByWorkIdIn(workIds);
            Map<String, List<ConstructionWorkSiteBean>> workSiteMap = Maps.newHashMap();
            if(CollectionUtils.isNotEmpty(workSiteBeanList)){
                workSiteMap = workSiteBeanList.stream().collect(Collectors.groupingBy(ConstructionWorkSiteBean::getConstructionWorkObjId));
            }

            // 2. 根据工程 ID，从 BarriersBean 中找到对应的设备类型
            List<BarriersBean> barriersList = lambdaQuery()
                    .in(BarriersBean::getConstructionWorkObjId, workIds) // 根据工程 ID 筛选
                    .eq(BarriersBean::getDistinguish, distinguish) // 根据工程 ID 筛选
                    .eq(BarriersBean::getIfDelete, BaseCodeConstants.CodeType_WhetherCode.KEY_WhetherCode02)
                    .list();

            // 按工程现场 ID 分组
            Map<String, List<BarriersBean>> barriersByWorkSiteId = barriersList.stream()
                    .collect(Collectors.groupingBy(BarriersBean::getConstructionWorkSiteObjId));

            Map<String, List<ConstructionWorkSiteBean>> finalWorkSiteMap = workSiteMap;
            constructionWorkBeanList.forEach(constructionWorkBean -> {
                BarriersTreeVO workNode = new BarriersTreeVO();
                workNode.setObjId(constructionWorkBean.getObjId());
                workNode.setObjName(constructionWorkBean.getWorkName());
                workNode.setType("01");
                workNode.setConstructionWorkObjId(constructionWorkBean.getObjId());
                
                // 工程现场
                if(finalWorkSiteMap.containsKey(constructionWorkBean.getObjId())){
                    List<ConstructionWorkSiteBean> constructionWorkSiteBeans = finalWorkSiteMap.get(constructionWorkBean.getObjId());
                    List<BarriersTreeVO> siteTreeVOList = Lists.newArrayList();
                    constructionWorkSiteBeans.forEach(constructionWorkSiteBean -> {
                        BarriersTreeVO siteNode = new BarriersTreeVO();
                        siteNode.setObjId(constructionWorkSiteBean.getObjId());
                        siteNode.setObjName(constructionWorkSiteService.getNewSiteName(constructionWorkSiteBean));
                        siteNode.setIfGrant(constructionWorkSiteBean.getIfGrant());
                        siteNode.setType("02");
                        siteNode.setConstructionWorkObjId(constructionWorkSiteBean.getConstructionWorkObjId());
                        siteNode.setConstructionWorkSiteObjId(constructionWorkSiteBean.getObjId());
                        
                        // 设备
                        if(barriersByWorkSiteId.containsKey(constructionWorkSiteBean.getObjId())){
                            List<BarriersBean> barriersBeans = barriersByWorkSiteId.get(constructionWorkSiteBean.getObjId());
                            List<BarriersTreeVO> barriersTreeVOList = Lists.newArrayList();
                            barriersBeans.forEach(barriersBean -> {
                                BarriersTreeVO barriersVO = new BarriersTreeVO();
                                barriersVO.setObjId(barriersBean.getObjId());
                                barriersVO.setObjName(barriersBean.getModel());
                                barriersVO.setType("03");
                                barriersVO.setOnlineStatus(barriersBean.getOnlineStatus());
                                barriersVO.setConstructionWorkObjId(barriersBean.getConstructionWorkObjId());
                                barriersVO.setConstructionWorkSiteObjId(barriersBean.getConstructionWorkSiteObjId());
                                barriersTreeVOList.add(barriersVO);
                            });
                            siteNode.setChildrenList(barriersTreeVOList);
                        }
                        
                        siteTreeVOList.add(siteNode);
                    });

                    workNode.setChildrenList(siteTreeVOList);
                }
                treeList.add(workNode);
            });
        }

        if(CollectionUtils.isNotEmpty(treeList)){
            OrgBean orgBean = null;
            String orgId = BaseCommonUtils.extractOrdIdByToken();
            // 补充上级单位
            if(!headOffice){
                String departmentOrgIdByOrgId = orgService.findDepartmentOrgIdByOrgId(orgId);
                orgBean = orgService.lambdaQuery().eq(OrgBean::getId, departmentOrgIdByOrgId).one();
            }else{
                orgBean = orgService.findRootNodeByOrgId(orgId);
            }
            if(Objects.nonNull(orgBean)){
                BarriersTreeVO treeVO = new BarriersTreeVO();
                treeVO.setObjId(orgBean.getId());
                treeVO.setObjName(orgBean.getName());
                treeVO.setChildrenList(treeList);
                treeVO.setType("001");
                List<BarriersTreeVO> treeVOList = Lists.newArrayList();
                treeVOList.add(treeVO);
                return treeVOList;
            }
        }
        

        return treeList;
    }

    /**
     * 根据产品序列号查询设备状态
     *
     * @param devSno 设备号
     * @return 装填
     */
    @Override
    public BarriersBaseVO findByFactorySerialNumberAndOnLine(String devSno) {
        BarriersBean barriersBean = this.lambdaQuery()
                .eq(BarriersBean::getFactorySerialNumber, devSno)
                .eq(BarriersBean::getIfDelete, BaseCodeConstants.CodeType_WhetherCode.KEY_WhetherCode02)
                .last(Constants.LAST_SQL)
                .one();
        BarriersBaseVO barriersBaseVO = null;
        if(Objects.nonNull(barriersBean)){
            barriersBaseVO = new BarriersBaseVO();
            BeanUtils.copyProperties(barriersBean, barriersBaseVO);
        }
        return barriersBaseVO;
    }

    /**
     * 设备在线
     *
     * @param devSno 设备号
     */
    @Override
    @Transactional(value = "transactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void beOnlineByFactorySerialNumber(String devSno) {
        this.lambdaUpdate()
                .set(BarriersBean::getOnlineStatus, BaseCodeConstants.CodeType_WhetherCode.KEY_WhetherCode01)
                .set(BarriersBean::getOnlineStatusUpdateTime, new Date())
                .eq(BarriersBean::getFactorySerialNumber, devSno)
                .eq(BarriersBean::getIfDelete, BaseCodeConstants.CodeType_WhetherCode.KEY_WhetherCode02)
                .update();
    }

    /**
     * 设备离线
     * @param devSno 设备号
     */
    @Override
    @Transactional(value = "transactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void offlineByFactorySerialNumber(String devSno) {
        this.lambdaUpdate()
                .set(BarriersBean::getOnlineStatus, BaseCodeConstants.CodeType_WhetherCode.KEY_WhetherCode02)
                .set(BarriersBean::getOnlineStatusUpdateTime, new Date())
                .eq(BarriersBean::getFactorySerialNumber, devSno)
                .eq(BarriersBean::getIfDelete, BaseCodeConstants.CodeType_WhetherCode.KEY_WhetherCode02)
                .update();
    }

    /**
     * 根据工程ID查询设备号
     *
     * @param workIdList 工程ID
     * @return 设备号
     */
    @Override
    public List<String> findFactorySerialNumberByWorkIdIn(List<String> workIdList, String onlineStatus) {
        List<BarriersBean> barriersBeanList = this.lambdaQuery()
                .in(BarriersBean::getConstructionWorkObjId, workIdList)
                .eq(BarriersBean::getIfDelete, BaseCodeConstants.CodeType_WhetherCode.KEY_WhetherCode02)
                .eq(StringUtils.isNotEmpty(onlineStatus), BarriersBean::getOnlineStatus, onlineStatus)
                .isNotNull(BarriersBean::getFactorySerialNumber).ne(BarriersBean::getFactorySerialNumber, "")
                .list();
        if(CollectionUtils.isNotEmpty(barriersBeanList)){
            return barriersBeanList.stream().map(BarriersBean::getFactorySerialNumber).collect(Collectors.toList());
        }
        return null;
    }

    @Override
    public List<BarriersBean> findByWorkIdInAndDistinguish(List<String> workIdList, String distinguish, String onlineStatus) {
        return this.lambdaQuery()
                .in(BarriersBean::getConstructionWorkObjId, workIdList)
                .eq(BarriersBean::getIfDelete, BaseCodeConstants.CodeType_WhetherCode.KEY_WhetherCode02)
                .eq(BarriersBean::getDistinguish, distinguish)
                .eq(StringUtils.isNotEmpty(onlineStatus), BarriersBean::getOnlineStatus, onlineStatus)
                .isNotNull(BarriersBean::getFactorySerialNumber).ne(BarriersBean::getFactorySerialNumber, "")
                .list();
    }

    /**
     * 根据设备类型查询道闸设备号
     *
     * @param distinguish 设备类型
     * @return 道闸设备号
     */
    @Override
    public List<String> findFactorySerialNumberByDistinguish(String distinguish) {
        List<BarriersBean> barriersBeanList = this.lambdaQuery()
                .eq(BarriersBean::getDistinguish, distinguish)
                .eq(BarriersBean::getIfDelete, BaseCodeConstants.CodeType_WhetherCode.KEY_WhetherCode02)
                .isNotNull(BarriersBean::getFactorySerialNumber).ne(BarriersBean::getFactorySerialNumber, "")
                .ne(BarriersBean::getFactorySerialNumber, "").list();
        if(CollectionUtils.isNotEmpty(barriersBeanList)){
            return barriersBeanList.stream().map(BarriersBean::getFactorySerialNumber).distinct().collect(Collectors.toList());
        }
        return null;
    }

    /**
     * 根据设备类型查询道闸设备号
     *
     * @param distinguish 设备类型
     * @param workIdList  施工工程ID
     * @return 道闸设备号
     */
    @Override
    public List<BarriersBean> findFactorySerialNumberByDistinguishAndWorkIdIn(String distinguish, List<String> workIdList) {
        return this.lambdaQuery()
                .eq(BarriersBean::getDistinguish, distinguish)
                .eq(BarriersBean::getIfDelete, BaseCodeConstants.CodeType_WhetherCode.KEY_WhetherCode02)
                .in(BarriersBean::getConstructionWorkObjId, workIdList)
                .isNotNull(BarriersBean::getFactorySerialNumber).ne(BarriersBean::getFactorySerialNumber, "")
                .ne(BarriersBean::getFactorySerialNumber, "").list();
    }

    /**
     * 根据设备号查询所属工程
     *
     * @param devSno 设备号
     * @return 工程ID
     */
    @Override
    public String findWorkIdByFactorySerialNumber(String devSno) {
        BarriersBean barriersBean = this.lambdaQuery()
                .eq(BarriersBean::getFactorySerialNumber, devSno)
                .eq(BarriersBean::getIfDelete, BaseCodeConstants.CodeType_WhetherCode.KEY_WhetherCode02)
                .last(Constants.LAST_SQL).one();
        if(Objects.nonNull(barriersBean)){
            return barriersBean.getConstructionWorkObjId();
        }
        return null;
    }

    /**
     * 更新设备在线状态
     */
    @Override
    @Transactional(value = "transactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void updateBarriersOnlineStatus() {
        LocalDateTime dateTime = LocalDateTime.now();
        dateTime = dateTime.minusMinutes(1);

        List<BarriersBean> barriersBeanList = this.lambdaQuery().le(BarriersBean::getOnlineStatusUpdateTime, dateTime)
                .eq(BarriersBean::getOnlineStatus, BaseCodeConstants.CodeType_WhetherCode.KEY_WhetherCode01).list();
        if(CollectionUtils.isNotEmpty(barriersBeanList)){
            barriersBeanList.forEach(barriersBean -> barriersBean.setOnlineStatus(BaseCodeConstants.CodeType_WhetherCode.KEY_WhetherCode02));

            boolean status = this.updateBatchById(barriersBeanList);
            if(status){
                // 设备离线，从首次登录中移除
                barriersBeanList.forEach(barriersBean -> Constants.firstSyncByBarrierGatePersonList.remove(barriersBean.getFactorySerialNumber()));
            }
        }
    }

    /**
     * 根据在线状态查询所有的设备
     *
     * @param onlineStatus 在线状态
     */
    @Override
    public List<BarriersBean> findAllByOnLineStatus(String onlineStatus) {
        return this.lambdaQuery().eq(BarriersBean::getOnlineStatus, onlineStatus)
                .eq(BarriersBean::getIfDelete, BaseCodeConstants.CodeType_WhetherCode.KEY_WhetherCode02)
                .list();
    }
}
